#pragma once 

#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>


#define ROOT "/"
#define DEVNULL "/dev/null"

void Daemon(bool ischdir, bool isclose)
{
    //守护进程需要忽略几个必要信号
    signal(SIGCHLD,SIG_IGN); //子进程退出信号
    signal(SIGPIPE,SIG_IGN); //管道读端退出，写端继续写

    //1. 不能为进程组的领导者，不能作为第一个进程
    if (fork() > 0) exit(0);

    //下面的操作就是子进程
    setsid(); //创建 ssession id

    //改变子进程的工作目录为根目录， 换位根目录之后可以更方便的访问系统资源 (绝对路径) 
    //当然也可以不改变，所以我们传入第一个参数ischdir
    if (ischdir) 
    {
        chdir(ROOT);
    }

    //关闭标准输入输出文件
    //但是我们不能直接关闭，由于代码中可能有往标准输出输出的步骤，如果直接关闭的话就会报错
    //所以我们传入第二个参数 isclose ,让用户自己来控制是否关闭
    if (isclose)
    {
        close(0);
        close(1);
        close(2);
    }
    else {
        int fd = open(DEVNULL,O_WRONLY);
        dup2(fd,0);
        dup2(fd,1);
        dup2(fd,2);
        close(fd); //把不需要的关闭即可，只有当一个文件的计数器--为0，才会彻底释放文件
    }
    
}